#include "fpsp-namespace.h"
//
//
//	get_op.sa 3.6 5/19/92
//
//	get_op.sa 3.5 4/26/91
//
//  Description: This routine is called by the unsupported format/data
// type exception handler ('unsupp' - vector 55) and the unimplemented
// instruction exception handler ('unimp' - vector 11).  'get_op'
// determines the opclass (0, 2, or 3) and branches to the
// opclass handler routine.  See 68881/2 User's Manual table 4-11
// for a description of the opclasses.
//
// For UNSUPPORTED data/format (exception vector 55) and for
// UNIMPLEMENTED instructions (exception vector 11) the following
// applies:
//
// - For unnormalized numbers (opclass 0, 2, or 3) the
// number(s) is normalized and the operand type tag is updated.
//
// - For a packed number (opclass 2) the number is unpacked and the
// operand type tag is updated.
//
// - For denormalized numbers (opclass 0 or 2) the number(s) is not
// changed but passed to the next module.  The next module for
// unimp is do_func, the next module for unsupp is res_func.
//
// For UNSUPPORTED data/format (exception vector 55) only the
// following applies:
//
// - If there is a move out with a packed number (opclass 3) the
// number is packed and written to user memory.  For the other
// opclasses the number(s) are written back to the fsave stack
// and the instruction is then restored back into the '040.  The
// '040 is then able to complete the instruction.
//
// For example:
// fadd.x fpm,fpn where the fpm contains an unnormalized number.
// The '040 takes an unsupported data trap and gets to this
// routine.  The number is normalized, put back on the stack and
// then an frestore is done to restore the instruction back into
// the '040.  The '040 then re-executes the fadd.x fpm,fpn with
// a normalized number in the source and the instruction is
// successful.
//
// Next consider if in the process of normalizing the un-
// normalized number it becomes a denormalized number.  The
// routine which converts the unnorm to a norm (called mk_norm)
// detects this and tags the number as a denorm.  The routine
// res_func sees the denorm tag and converts the denorm to a
// norm.  The instruction is then restored back into the '040
// which re_executes the instruction.
//
//
//		Copyright (C) Motorola, Inc. 1990
//			All Rights Reserved
//
//	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MOTOROLA
//	The copyright notice above does not evidence any
//	actual or intended publication of such source code.

GET_OP:    //idnt    2,1 | Motorola 040 Floating Point Software Package

	|section	8

#include "fpsp.defs"

	.global	PIRN,PIRZRM,PIRP
	.global	SMALRN,SMALRZRM,SMALRP
	.global	BIGRN,BIGRZRM,BIGRP

PIRN:
	.long 0x40000000,0xc90fdaa2,0x2168c235    //pi
PIRZRM:
	.long 0x40000000,0xc90fdaa2,0x2168c234    //pi
PIRP:
	.long 0x40000000,0xc90fdaa2,0x2168c235    //pi

//round to nearest
SMALRN:
	.long 0x3ffd0000,0x9a209a84,0xfbcff798    //log10(2)
	.long 0x40000000,0xadf85458,0xa2bb4a9a    //e
	.long 0x3fff0000,0xb8aa3b29,0x5c17f0bc    //log2(e)
	.long 0x3ffd0000,0xde5bd8a9,0x37287195    //log10(e)
	.long 0x00000000,0x00000000,0x00000000    //0.0
// round to zero;round to negative infinity
SMALRZRM:
	.long 0x3ffd0000,0x9a209a84,0xfbcff798    //log10(2)
	.long 0x40000000,0xadf85458,0xa2bb4a9a    //e
	.long 0x3fff0000,0xb8aa3b29,0x5c17f0bb    //log2(e)
	.long 0x3ffd0000,0xde5bd8a9,0x37287195    //log10(e)
	.long 0x00000000,0x00000000,0x00000000    //0.0
// round to positive infinity
SMALRP:
	.long 0x3ffd0000,0x9a209a84,0xfbcff799    //log10(2)
	.long 0x40000000,0xadf85458,0xa2bb4a9b    //e
	.long 0x3fff0000,0xb8aa3b29,0x5c17f0bc    //log2(e)
	.long 0x3ffd0000,0xde5bd8a9,0x37287195    //log10(e)
	.long 0x00000000,0x00000000,0x00000000    //0.0

//round to nearest
BIGRN:
	.long 0x3ffe0000,0xb17217f7,0xd1cf79ac    //ln(2)
	.long 0x40000000,0x935d8ddd,0xaaa8ac17    //ln(10)
	.long 0x3fff0000,0x80000000,0x00000000    //10 ^ 0

	.global	PTENRN
PTENRN:
	.long 0x40020000,0xA0000000,0x00000000    //10 ^ 1
	.long 0x40050000,0xC8000000,0x00000000    //10 ^ 2
	.long 0x400C0000,0x9C400000,0x00000000    //10 ^ 4
	.long 0x40190000,0xBEBC2000,0x00000000    //10 ^ 8
	.long 0x40340000,0x8E1BC9BF,0x04000000    //10 ^ 16
	.long 0x40690000,0x9DC5ADA8,0x2B70B59E    //10 ^ 32
	.long 0x40D30000,0xC2781F49,0xFFCFA6D5    //10 ^ 64
	.long 0x41A80000,0x93BA47C9,0x80E98CE0    //10 ^ 128
	.long 0x43510000,0xAA7EEBFB,0x9DF9DE8E    //10 ^ 256
	.long 0x46A30000,0xE319A0AE,0xA60E91C7    //10 ^ 512
	.long 0x4D480000,0xC9767586,0x81750C17    //10 ^ 1024
	.long 0x5A920000,0x9E8B3B5D,0xC53D5DE5    //10 ^ 2048
	.long 0x75250000,0xC4605202,0x8A20979B    //10 ^ 4096
//round to minus infinity
BIGRZRM:
	.long 0x3ffe0000,0xb17217f7,0xd1cf79ab    //ln(2)
	.long 0x40000000,0x935d8ddd,0xaaa8ac16    //ln(10)
	.long 0x3fff0000,0x80000000,0x00000000    //10 ^ 0

	.global	PTENRM
PTENRM:
	.long 0x40020000,0xA0000000,0x00000000    //10 ^ 1
	.long 0x40050000,0xC8000000,0x00000000    //10 ^ 2
	.long 0x400C0000,0x9C400000,0x00000000    //10 ^ 4
	.long 0x40190000,0xBEBC2000,0x00000000    //10 ^ 8
	.long 0x40340000,0x8E1BC9BF,0x04000000    //10 ^ 16
	.long 0x40690000,0x9DC5ADA8,0x2B70B59D    //10 ^ 32
	.long 0x40D30000,0xC2781F49,0xFFCFA6D5    //10 ^ 64
	.long 0x41A80000,0x93BA47C9,0x80E98CDF    //10 ^ 128
	.long 0x43510000,0xAA7EEBFB,0x9DF9DE8D    //10 ^ 256
	.long 0x46A30000,0xE319A0AE,0xA60E91C6    //10 ^ 512
	.long 0x4D480000,0xC9767586,0x81750C17    //10 ^ 1024
	.long 0x5A920000,0x9E8B3B5D,0xC53D5DE5    //10 ^ 2048
	.long 0x75250000,0xC4605202,0x8A20979A    //10 ^ 4096
//round to positive infinity
BIGRP:
	.long 0x3ffe0000,0xb17217f7,0xd1cf79ac    //ln(2)
	.long 0x40000000,0x935d8ddd,0xaaa8ac17    //ln(10)
	.long 0x3fff0000,0x80000000,0x00000000    //10 ^ 0

	.global	PTENRP
PTENRP:
	.long 0x40020000,0xA0000000,0x00000000    //10 ^ 1
	.long 0x40050000,0xC8000000,0x00000000    //10 ^ 2
	.long 0x400C0000,0x9C400000,0x00000000    //10 ^ 4
	.long 0x40190000,0xBEBC2000,0x00000000    //10 ^ 8
	.long 0x40340000,0x8E1BC9BF,0x04000000    //10 ^ 16
	.long 0x40690000,0x9DC5ADA8,0x2B70B59E    //10 ^ 32
	.long 0x40D30000,0xC2781F49,0xFFCFA6D6    //10 ^ 64
	.long 0x41A80000,0x93BA47C9,0x80E98CE0    //10 ^ 128
	.long 0x43510000,0xAA7EEBFB,0x9DF9DE8E    //10 ^ 256
	.long 0x46A30000,0xE319A0AE,0xA60E91C7    //10 ^ 512
	.long 0x4D480000,0xC9767586,0x81750C18    //10 ^ 1024
	.long 0x5A920000,0x9E8B3B5D,0xC53D5DE6    //10 ^ 2048
	.long 0x75250000,0xC4605202,0x8A20979B    //10 ^ 4096

	|xref	nrm_zero
	|xref	decbin
	|xref	round

	.global    get_op
	.global    uns_getop
	.global    uni_getop
get_op:
	clrb	DY_MO_FLG(%a6)
	tstb	UFLG_TMP(%a6)	//test flag for unsupp/unimp state
	beq	uni_getop

uns_getop:
	btstb	#direction_bit,CMDREG1B(%a6)
	bne	opclass3	//branch if a fmove out (any kind)
	btstb	#6,CMDREG1B(%a6)
	beqs	uns_notpacked

	bfextu	CMDREG1B(%a6){#3:#3},%d0
	cmpb	#3,%d0
	beq	pack_source	//check for a packed src op, branch if so
uns_notpacked:
	bsr	chk_dy_mo	//set the dyadic/monadic flag
	tstb	DY_MO_FLG(%a6)
	beqs	src_op_ck	//if monadic, go check src op
//				;else, check dst op (fall through)

	btstb	#7,DTAG(%a6)
	beqs	src_op_ck	//if dst op is norm, check src op
	bras	dst_ex_dnrm	//else, handle destination unnorm/dnrm

uni_getop:
	bfextu	CMDREG1B(%a6){#0:#6},%d0 //get opclass and src fields
	cmpil	#0x17,%d0		//if op class and size fields are $17,
//				;it is FMOVECR; if not, continue
//
// If the instruction is fmovecr, exit get_op.  It is handled
// in do_func and smovecr.sa.
//
	bne	not_fmovecr	//handle fmovecr as an unimplemented inst
	rts

not_fmovecr:
	btstb	#E1,E_BYTE(%a6)	//if set, there is a packed operand
	bne	pack_source	//check for packed src op, branch if so

// The following lines of are coded to optimize on normalized operands
	moveb	STAG(%a6),%d0
	orb	DTAG(%a6),%d0	//check if either of STAG/DTAG msb set
	bmis	dest_op_ck	//if so, some op needs to be fixed
	rts

dest_op_ck:
	btstb	#7,DTAG(%a6)	//check for unsupported data types in
	beqs	src_op_ck	//the destination, if not, check src op
	bsr	chk_dy_mo	//set dyadic/monadic flag
	tstb	DY_MO_FLG(%a6)	//
	beqs	src_op_ck	//if monadic, check src op
//
// At this point, destination has an extended denorm or unnorm.
//
dst_ex_dnrm:
	movew	FPTEMP_EX(%a6),%d0 //get destination exponent
	andiw	#0x7fff,%d0	//mask sign, check if exp = 0000
	beqs	src_op_ck	//if denorm then check source op.
//				;denorms are taken care of in res_func
//				;(unsupp) or do_func (unimp)
//				;else unnorm fall through
	leal	FPTEMP(%a6),%a0	//point a0 to dop - used in mk_norm
	bsr	mk_norm		//go normalize - mk_norm returns:
//				;L_SCR1{7:5} = operand tag
//				;	(000 = norm, 100 = denorm)
//				;L_SCR1{4} = fpte15 or ete15
//				;	0 = exp >  $3fff
//				;	1 = exp <= $3fff
//				;and puts the normalized num back
//				;on the fsave stack
//
	moveb L_SCR1(%a6),DTAG(%a6) //write the new tag & fpte15
//				;to the fsave stack and fall
//				;through to check source operand
//
src_op_ck:
	btstb	#7,STAG(%a6)
	beq	end_getop	//check for unsupported data types on the
//				;source operand
	btstb	#5,STAG(%a6)
	bnes	src_sd_dnrm	//if bit 5 set, handle sgl/dbl denorms
//
// At this point only unnorms or extended denorms are possible.
//
src_ex_dnrm:
	movew	ETEMP_EX(%a6),%d0 //get source exponent
	andiw	#0x7fff,%d0	//mask sign, check if exp = 0000
	beq	end_getop	//if denorm then exit, denorms are
//				;handled in do_func
	leal	ETEMP(%a6),%a0	//point a0 to sop - used in mk_norm
	bsr	mk_norm		//go normalize - mk_norm returns:
//				;L_SCR1{7:5} = operand tag
//				;	(000 = norm, 100 = denorm)
//				;L_SCR1{4} = fpte15 or ete15
//				;	0 = exp >  $3fff
//				;	1 = exp <= $3fff
//				;and puts the normalized num back
//				;on the fsave stack
//
	moveb	L_SCR1(%a6),STAG(%a6) //write the new tag & ete15
	rts			//end_getop

//
// At this point, only single or double denorms are possible.
// If the inst is not fmove, normalize the source.  If it is,
// do nothing to the input.
//
src_sd_dnrm:
	btstb	#4,CMDREG1B(%a6)	//differentiate between sgl/dbl denorm
	bnes	is_double
is_single:
	movew	#0x3f81,%d1	//write bias for sgl denorm
	bras	common		//goto the common code
is_double:
	movew	#0x3c01,%d1	//write the bias for a dbl denorm
common:
	btstb	#sign_bit,ETEMP_EX(%a6) //grab sign bit of mantissa
	beqs	pos
	bset	#15,%d1		//set sign bit because it is negative
pos:
	movew	%d1,ETEMP_EX(%a6)
//				;put exponent on stack

	movew	CMDREG1B(%a6),%d1
	andw	#0xe3ff,%d1	//clear out source specifier
	orw	#0x0800,%d1	//set source specifier to extended prec
	movew	%d1,CMDREG1B(%a6)	//write back to the command word in stack
//				;this is needed to fix unsupp data stack
	leal	ETEMP(%a6),%a0	//point a0 to sop

	bsr	mk_norm		//convert sgl/dbl denorm to norm
	moveb	L_SCR1(%a6),STAG(%a6) //put tag into source tag reg - d0
	rts			//end_getop
//
// At this point, the source is definitely packed, whether
// instruction is dyadic or monadic is still unknown
//
pack_source:
	movel	FPTEMP_LO(%a6),ETEMP(%a6)	//write ms part of packed
//				;number to etemp slot
	bsr	chk_dy_mo	//set dyadic/monadic flag
	bsr	unpack

	tstb	DY_MO_FLG(%a6)
	beqs	end_getop	//if monadic, exit
//				;else, fix FPTEMP
pack_dya:
	bfextu	CMDREG1B(%a6){#6:#3},%d0 //extract dest fp reg
	movel	#7,%d1
	subl	%d0,%d1
	clrl	%d0
	bsetl	%d1,%d0		//set up d0 as a dynamic register mask
	fmovemx %d0,FPTEMP(%a6)	//write to FPTEMP

	btstb	#7,DTAG(%a6)	//check dest tag for unnorm or denorm
	bne	dst_ex_dnrm	//else, handle the unnorm or ext denorm
//
// Dest is not denormalized.  Check for norm, and set fpte15
// accordingly.
//
	moveb	DTAG(%a6),%d0
	andib	#0xf0,%d0		//strip to only dtag:fpte15
	tstb	%d0		//check for normalized value
	bnes	end_getop	//if inf/nan/zero leave get_op
	movew	FPTEMP_EX(%a6),%d0
	andiw	#0x7fff,%d0
	cmpiw	#0x3fff,%d0	//check if fpte15 needs setting
	bges	end_getop	//if >= $3fff, leave fpte15=0
	orb	#0x10,DTAG(%a6)
	bras	end_getop

//
// At this point, it is either an fmoveout packed, unnorm or denorm
//
opclass3:
	clrb	DY_MO_FLG(%a6)	//set dyadic/monadic flag to monadic
	bfextu	CMDREG1B(%a6){#4:#2},%d0
	cmpib	#3,%d0
	bne	src_ex_dnrm	//if not equal, must be unnorm or denorm
//				;else it is a packed move out
//				;exit
end_getop:
	rts

//
// Sets the DY_MO_FLG correctly. This is used only on if it is an
// unsupported data type exception.  Set if dyadic.
//
chk_dy_mo:
	movew	CMDREG1B(%a6),%d0
	btstl	#5,%d0		//testing extension command word
	beqs	set_mon		//if bit 5 = 0 then monadic
	btstl	#4,%d0		//know that bit 5 = 1
	beqs	set_dya		//if bit 4 = 0 then dyadic
	andiw	#0x007f,%d0	//get rid of all but extension bits {6:0}
	cmpiw 	#0x0038,%d0	//if extension = $38 then fcmp (dyadic)
	bnes	set_mon
set_dya:
	st	DY_MO_FLG(%a6)	//set the inst flag type to dyadic
	rts
set_mon:
	clrb	DY_MO_FLG(%a6)	//set the inst flag type to monadic
	rts
//
//	MK_NORM
//
// Normalizes unnormalized numbers, sets tag to norm or denorm, sets unfl
// exception if denorm.
//
// CASE opclass 0x0 unsupp
//	mk_norm till msb set
//	set tag = norm
//
// CASE opclass 0x0 unimp
//	mk_norm till msb set or exp = 0
//	if integer bit = 0
//	   tag = denorm
//	else
//	   tag = norm
//
// CASE opclass 011 unsupp
//	mk_norm till msb set or exp = 0
//	if integer bit = 0
//	   tag = denorm
//	   set unfl_nmcexe = 1
//	else
//	   tag = norm
//
// if exp <= $3fff
//   set ete15 or fpte15 = 1
// else set ete15 or fpte15 = 0

// input:
//	a0 = points to operand to be normalized
// output:
//	L_SCR1{7:5} = operand tag (000 = norm, 100 = denorm)
//	L_SCR1{4}   = fpte15 or ete15 (0 = exp > $3fff, 1 = exp <=$3fff)
//	the normalized operand is placed back on the fsave stack
mk_norm:
	clrl	L_SCR1(%a6)
	bclrb	#sign_bit,LOCAL_EX(%a0)
	sne	LOCAL_SGN(%a0)	//transform into internal extended format

	cmpib	#0x2c,1+EXC_VEC(%a6) //check if unimp
	bnes	uns_data	//branch if unsupp
	bsr	uni_inst	//call if unimp (opclass 0x0)
	bras	reload
uns_data:
	btstb	#direction_bit,CMDREG1B(%a6) //check transfer direction
	bnes	bit_set		//branch if set (opclass 011)
	bsr	uns_opx		//call if opclass 0x0
	bras	reload
bit_set:
	bsr	uns_op3		//opclass 011
reload:
	cmpw	#0x3fff,LOCAL_EX(%a0) //if exp > $3fff
	bgts	end_mk		//   fpte15/ete15 already set to 0
	bsetb	#4,L_SCR1(%a6)	//else set fpte15/ete15 to 1
//				;calling routine actually sets the
//				;value on the stack (along with the
//				;tag), since this routine doesn't
//				;know if it should set ete15 or fpte15
//				;ie, it doesn't know if this is the
//				;src op or dest op.
end_mk:
	bfclr	LOCAL_SGN(%a0){#0:#8}
	beqs	end_mk_pos
	bsetb	#sign_bit,LOCAL_EX(%a0) //convert back to IEEE format
end_mk_pos:
	rts
//
//     CASE opclass 011 unsupp
//
uns_op3:
	bsr	nrm_zero	//normalize till msb = 1 or exp = zero
	btstb	#7,LOCAL_HI(%a0)	//if msb = 1
	bnes	no_unfl		//then branch
set_unfl:
	orw	#dnrm_tag,L_SCR1(%a6) //set denorm tag
	bsetb	#unfl_bit,FPSR_EXCEPT(%a6) //set unfl exception bit
no_unfl:
	rts
//
//     CASE opclass 0x0 unsupp
//
uns_opx:
	bsr	nrm_zero	//normalize the number
	btstb	#7,LOCAL_HI(%a0)	//check if integer bit (j-bit) is set
	beqs	uns_den		//if clear then now have a denorm
uns_nrm:
	orb	#norm_tag,L_SCR1(%a6) //set tag to norm
	rts
uns_den:
	orb	#dnrm_tag,L_SCR1(%a6) //set tag to denorm
	rts
//
//     CASE opclass 0x0 unimp
//
uni_inst:
	bsr	nrm_zero
	btstb	#7,LOCAL_HI(%a0)	//check if integer bit (j-bit) is set
	beqs	uni_den		//if clear then now have a denorm
uni_nrm:
	orb	#norm_tag,L_SCR1(%a6) //set tag to norm
	rts
uni_den:
	orb	#dnrm_tag,L_SCR1(%a6) //set tag to denorm
	rts

//
//	Decimal to binary conversion
//
// Special cases of inf and NaNs are completed outside of decbin.
// If the input is an snan, the snan bit is not set.
//
// input:
//	ETEMP(a6)	- points to packed decimal string in memory
// output:
//	fp0	- contains packed string converted to extended precision
//	ETEMP	- same as fp0
unpack:
	movew	CMDREG1B(%a6),%d0	//examine command word, looking for fmove's
	andw	#0x3b,%d0
	beq	move_unpack	//special handling for fmove: must set FPSR_CC

	movew	ETEMP(%a6),%d0	//get word with inf information
	bfextu	%d0{#20:#12},%d1	//get exponent into d1
	cmpiw	#0x0fff,%d1	//test for inf or NaN
	bnes	try_zero	//if not equal, it is not special
	bfextu	%d0{#17:#3},%d1	//get SE and y bits into d1
	cmpiw	#7,%d1		//SE and y bits must be on for special
	bnes	try_zero	//if not on, it is not special
//input is of the special cases of inf and NaN
	tstl	ETEMP_HI(%a6)	//check ms mantissa
	bnes	fix_nan		//if non-zero, it is a NaN
	tstl	ETEMP_LO(%a6)	//check ls mantissa
	bnes	fix_nan		//if non-zero, it is a NaN
	bra	finish		//special already on stack
fix_nan:
	btstb	#signan_bit,ETEMP_HI(%a6) //test for snan
	bne	finish
	orl	#snaniop_mask,USER_FPSR(%a6) //always set snan if it is so
	bra	finish
try_zero:
	movew	ETEMP_EX+2(%a6),%d0 //get word 4
	andiw	#0x000f,%d0	//clear all but last ni(y)bble
	tstw	%d0		//check for zero.
	bne	not_spec
	tstl	ETEMP_HI(%a6)	//check words 3 and 2
	bne	not_spec
	tstl	ETEMP_LO(%a6)	//check words 1 and 0
	bne	not_spec
	tstl	ETEMP(%a6)	//test sign of the zero
	bges	pos_zero
	movel	#0x80000000,ETEMP(%a6) //write neg zero to etemp
	clrl	ETEMP_HI(%a6)
	clrl	ETEMP_LO(%a6)
	bra	finish
pos_zero:
	clrl	ETEMP(%a6)
	clrl	ETEMP_HI(%a6)
	clrl	ETEMP_LO(%a6)
	bra	finish

not_spec:
	fmovemx %fp0-%fp1,-(%a7)	//save fp0 - decbin returns in it
	bsr	decbin
	fmovex %fp0,ETEMP(%a6)	//put the unpacked sop in the fsave stack
	fmovemx (%a7)+,%fp0-%fp1
	fmovel	#0,%FPSR		//clr fpsr from decbin
	bra	finish

//
// Special handling for packed move in:  Same results as all other
// packed cases, but we must set the FPSR condition codes properly.
//
move_unpack:
	movew	ETEMP(%a6),%d0	//get word with inf information
	bfextu	%d0{#20:#12},%d1	//get exponent into d1
	cmpiw	#0x0fff,%d1	//test for inf or NaN
	bnes	mtry_zero	//if not equal, it is not special
	bfextu	%d0{#17:#3},%d1	//get SE and y bits into d1
	cmpiw	#7,%d1		//SE and y bits must be on for special
	bnes	mtry_zero	//if not on, it is not special
//input is of the special cases of inf and NaN
	tstl	ETEMP_HI(%a6)	//check ms mantissa
	bnes	mfix_nan		//if non-zero, it is a NaN
	tstl	ETEMP_LO(%a6)	//check ls mantissa
	bnes	mfix_nan		//if non-zero, it is a NaN
//input is inf
	orl	#inf_mask,USER_FPSR(%a6) //set I bit
	tstl	ETEMP(%a6)	//check sign
	bge	finish
	orl	#neg_mask,USER_FPSR(%a6) //set N bit
	bra	finish		//special already on stack
mfix_nan:
	orl	#nan_mask,USER_FPSR(%a6) //set NaN bit
	moveb	#nan_tag,STAG(%a6)	//set stag to NaN
	btstb	#signan_bit,ETEMP_HI(%a6) //test for snan
	bnes	mn_snan
	orl	#snaniop_mask,USER_FPSR(%a6) //set snan bit
	btstb	#snan_bit,FPCR_ENABLE(%a6) //test for snan enabled
	bnes	mn_snan
	bsetb	#signan_bit,ETEMP_HI(%a6) //force snans to qnans
mn_snan:
	tstl	ETEMP(%a6)	//check for sign
	bge	finish		//if clr, go on
	orl	#neg_mask,USER_FPSR(%a6) //set N bit
	bra	finish

mtry_zero:
	movew	ETEMP_EX+2(%a6),%d0 //get word 4
	andiw	#0x000f,%d0	//clear all but last ni(y)bble
	tstw	%d0		//check for zero.
	bnes	mnot_spec
	tstl	ETEMP_HI(%a6)	//check words 3 and 2
	bnes	mnot_spec
	tstl	ETEMP_LO(%a6)	//check words 1 and 0
	bnes	mnot_spec
	tstl	ETEMP(%a6)	//test sign of the zero
	bges	mpos_zero
	orl	#neg_mask+z_mask,USER_FPSR(%a6) //set N and Z
	movel	#0x80000000,ETEMP(%a6) //write neg zero to etemp
	clrl	ETEMP_HI(%a6)
	clrl	ETEMP_LO(%a6)
	bras	finish
mpos_zero:
	orl	#z_mask,USER_FPSR(%a6) //set Z
	clrl	ETEMP(%a6)
	clrl	ETEMP_HI(%a6)
	clrl	ETEMP_LO(%a6)
	bras	finish

mnot_spec:
	fmovemx %fp0-%fp1,-(%a7)	//save fp0 ,fp1 - decbin returns in fp0
	bsr	decbin
	fmovex %fp0,ETEMP(%a6)
//				;put the unpacked sop in the fsave stack
	fmovemx (%a7)+,%fp0-%fp1

finish:
	movew	CMDREG1B(%a6),%d0	//get the command word
	andw	#0xfbff,%d0	//change the source specifier field to
//				;extended (was packed).
	movew	%d0,CMDREG1B(%a6)	//write command word back to fsave stack
//				;we need to do this so the 040 will
//				;re-execute the inst. without taking
//				;another packed trap.

fix_stag:
//Converted result is now in etemp on fsave stack, now set the source
//tag (stag)
//	if (ete =$7fff) then INF or NAN
//		if (etemp = $x.0----0) then
//			stag = INF
//		else
//			stag = NAN
//	else
//		if (ete = $0000) then
//			stag = ZERO
//		else
//			stag = NORM
//
// Note also that the etemp_15 bit (just right of the stag) must
// be set accordingly.
//
	movew		ETEMP_EX(%a6),%d1
	andiw		#0x7fff,%d1   //strip sign
	cmpw  		#0x7fff,%d1
	bnes  		z_or_nrm
	movel		ETEMP_HI(%a6),%d1
	bnes		is_nan
	movel		ETEMP_LO(%a6),%d1
	bnes		is_nan
is_inf:
	moveb		#0x40,STAG(%a6)
	movel		#0x40,%d0
	rts
is_nan:
	moveb		#0x60,STAG(%a6)
	movel		#0x60,%d0
	rts
z_or_nrm:
	tstw		%d1
	bnes		is_nrm
is_zro:
// For a zero, set etemp_15
	moveb		#0x30,STAG(%a6)
	movel		#0x20,%d0
	rts
is_nrm:
// For a norm, check if the exp <= $3fff; if so, set etemp_15
	cmpiw		#0x3fff,%d1
	bles		set_bit15
	moveb		#0,STAG(%a6)
	bras		end_is_nrm
set_bit15:
	moveb		#0x10,STAG(%a6)
end_is_nrm:
	movel		#0,%d0
end_fix:
	rts

end_get:
	rts
	|end
